/*
 * Controller.java
 *
 * Created on 27 de Setembro de 2006, 19:25
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package br.ufal.ic.forbile.controller;

import br.ufal.ic.forbile.agents.persistence.PersistenceOWLAgentInteraction;
import br.ufal.ic.forbile.agents.sa.SupportAgent;
import br.ufal.ic.forbile.agents.ata.ATAAgent;
import br.ufal.ic.forbile.agents.mediator.MediatorAgent;
import br.ufal.ic.forbile.agents.persistence.PersistenceAgent;
import br.ufal.ic.forbile.agents.persistence.PersistenceEMATHEMAAgent;
import br.ufal.ic.forbile.exceptions.ForBILEException;
import br.ufal.ic.forbile.infra.emathema.ontology.Curriculum;
import br.ufal.ic.forbile.log.PersistenceOWLLog;
import br.ufal.ic.utils.Constants;
import br.ufal.ic.utils.RegionServer;
import br.ufal.ic.utils.SharedMem;
import edu.stanford.smi.protegex.owl.model.OWLIndividual;
import edu.stanford.smi.protegex.owl.model.RDFResource;
import jade.Boot;
import jade.core.Profile;
import jade.core.ProfileImpl;
import jade.wrapper.AgentContainer;
import jade.wrapper.AgentController;
import jade.wrapper.StaleProxyException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author zero
 */
public class Controller {
    private static Controller instance;
    
    // Jade necessities
    private jade.core.Runtime runtime;
    
    // Social Knowledge
    private MediatorAgent                mediator;
    private PersistenceAgent             persistenceEMATHEMA;
    private PersistenceAgent             persistenceInteraction;
    private ATAAgent                     ata;
    private SupportAgent                 ada;

    /**
     * Creates a new instance of Controller
     */
    private Controller() {
        Boot.main(new String[]{"-gui"});
        
        runtime = jade.core.Runtime.instance();
        
        persistenceInteraction = new PersistenceOWLAgentInteraction("", "");
        
        mediator = new MediatorAgent("MediatorContainer", "MediatorAgent");
        
        persistenceEMATHEMA = new PersistenceEMATHEMAAgent("", "");
        
        //ata = new CognitiveAgent("", "");
        
        try {
            start();
        } catch (StaleProxyException ex) {
            new ForBILEException("Controller Agent could not be started", ex);
        }
        
    }
    
    public static Controller getInstance() {
        if (instance == null) {
            instance = new Controller();
        }
        return instance;
    }
    
    private void startSocietyAgents() throws StaleProxyException {
        Profile profile = new ProfileImpl();
        profile.setParameter(profile.CONTAINER_NAME, "SocietyAgentContainer");
        
        AgentContainer ATAAgentContainer =
                runtime.createAgentContainer(profile);
        
        
        // Retrieve curriculum list to built the society of agents.
        /*    public void requestPersistence(final String method, final Map configuration,
                    final String subject, final String predicate, final String object,
                    final String individual, final String class_, final Map retrieve, final String retrieveKey,
                    final OWLIndividual individualOWL){ */
        
        try {
            Thread.sleep(4000);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        
        
        Map m = new HashMap();
        
        m = (Map) retrieve(null, "rdf:type", ":Curriculum");
        
        List<AgentController> controllerATAs = new ArrayList<AgentController>();
        
        int i = 1;
        
        for ( Object o : m.keySet() ) {
            
            OWLIndividual owli = (OWLIndividual) m.get(o);
            Curriculum curriculum = null;
            
            RDFResource res = owli.as(Curriculum.class);
            curriculum = (Curriculum) res;
            
            //ATAAgent ata = new CognitiveAgent("", "");
            
            //controllerATAs.add( ATAAgentContainer.acceptNewAgent(( "AT:" + curriculum.getName() ), ata) );
        }

        for (AgentController ac : controllerATAs) {
            try {
                Thread.sleep(1200);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            
            ac.start();
        }

        
        System.out.println("--------------------------------------------");
        System.out.println("            Agent Society Builded           ");
        System.out.println("--------------------------------------------");
    }
    
    private void startPersistentAgents() throws StaleProxyException {
        Profile profile = new ProfileImpl();
        profile.setParameter(profile.CONTAINER_NAME, "PersistentContainer");
        
        AgentContainer persistentAgentContainer =
                runtime.createAgentContainer(profile);
        
        AgentController controllerPersistence;
        AgentController controllerPersistence2;
        
        controllerPersistence  = persistentAgentContainer.acceptNewAgent("PersistenceEMATHEMAAgent", persistenceEMATHEMA);
        controllerPersistence2 = persistentAgentContainer.acceptNewAgent("PersistenceOWLAgentInteraction", persistenceInteraction);
        
        controllerPersistence2.start();
        try {
            
            Thread.sleep(8000);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        
        controllerPersistence.start();
    }

    private void startMediatorAgent() throws StaleProxyException {
        Profile profile = new ProfileImpl();
        profile.setParameter(profile.CONTAINER_NAME, "MediatorContainer");

        AgentContainer mediatorAgentContainer =
                runtime.createAgentContainer(profile);

        AgentController controller = mediatorAgentContainer.acceptNewAgent("MediatorAgent", mediator);
        System.out.println("Vai colocar o mediador em um container");

        try {
            Thread.sleep(5000);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }

        controller.start();
    }
    
    private void start() throws StaleProxyException {
        // Start default agents
        startPersistentAgents();
        startMediatorAgent();
        //startSocietyAgents();
    }
    
    public void teach(final String instrutionalPlan) {
        try {
            startSocietyAgents();
        } catch (StaleProxyException ex) {
            ex.printStackTrace();
        }
        mediator.teach(instrutionalPlan);
    }
    
    public Object requestPersistence(String method, Map configuration,
            String subject, String predicate, String object,
            String individual, String class_, Map retrieve, String retrieveKey, /* retrieveKey: Map or Individual */
            OWLIndividual individualOWL) {
        
        PersistenceOWLLog pl = new PersistenceOWLLog();
        
        pl.setMethod(method);
        pl.setConfiguration(configuration);
        
        pl.setSubject(subject);
        pl.setPredicate(predicate);
        pl.setObject(object);
        
        pl.setRetrieve(retrieve);
        pl.setRetrieveKey(retrieveKey);
        
        pl.setClass_(class_);
        pl.setIndividual(individual);
        pl.setIndividualOWL(individualOWL);

        pl.setOwlFile("emathema");

        System.out.println("Vai Escrever");
        try {
            SharedMem mem = (SharedMem) Naming.lookup(RegionServer.HOST_URL);
            mem.getRegion(Constants.OWLPersistence).write(pl);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        System.out.println("Escreveu");

        //mediator.requestPersistence(pl.getMethod(), "EMATHEMA");

        PersistenceOWLLog persistenceLog = new PersistenceOWLLog();

        boolean flag;
        do {
            flag = false;
            try {
                SharedMem mem = (SharedMem) Naming.lookup(RegionServer.HOST_URL);
                persistenceLog = (PersistenceOWLLog)
                mem.getRegion(Constants.OWLPersistence).read(pl);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            
            if (persistenceLog != null) {
                if (persistenceLog.getIndividual() == null
                        || persistenceLog.getRetrieve() == null) {
                    flag = true;
                }
            }
            
            if (!flag) {
                try {
                    SharedMem mem = (SharedMem) Naming.lookup(RegionServer.HOST_URL);
                    persistenceLog = (PersistenceOWLLog)
                    mem.getRegion(Constants.OWLPersistence).retrieveIfExist(pl);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        } while(flag);
        
        System.out.println("Recuperou" + persistenceLog);
        
        if ( retrieveKey == null ) {
            return null;
        }
        if          ( retrieveKey.equals("Map") ) {
            return persistenceLog.getRetrieve();
        } else { return persistenceLog.getIndividualOWL(); }
    }
    
    public void manageAgents(){
        //mediator.manageCognitiveAgents(persistenceEMATHEMA);
    }
    
    public void infer(){
    }
    
    public void create(Map configuration){
        requestPersistence("CREATE", configuration,
                null, null, null,
                null, null, null, null,
                null);
    }
    
    public Map retrieve(String subject, String predicate, String object) {
        return (Map) requestPersistence("RETRIEVE", null,
                subject, predicate, object,
                null, null, null, "Map",
                null);
    }
    
    public OWLIndividual retrieve(String individual, String class_) {
        return (OWLIndividual) requestPersistence("RETRIEVE", null,
                null, null, null,
                individual, class_, null, "Individual",
                null);
    }
    
    public void update(Map configuration){
        requestPersistence("UPDATE", configuration,
                null, null, null,
                null, null, null, null,
                null);
    }
    
    public void delete(Map configuration){
        requestPersistence("DELETE", configuration,
                null, null, null,
                null, null, null, null,
                null);
    }
}
